﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace UNSWThink
{
   /// <summary>
   /// Windows form that handles adding and editing questions
   /// </summary>
   public partial class AddEditQuestionForm : Form
   {
      private bool mode;
      private DBConnection dbConnection;
      private int newClassID;
      private int questionID;
      private int answerID;
      private DataTable questionTable;
      private DataTable answerTable;
      private int questionRowIndex;
      private int questionNum;
      private DataTable relatedAnswers;

      /// <summary>
      /// Default constructor
      /// </summary>
      /// <param name="mode">
      /// States the type of mode the form is to function as
      /// </param>
      /// <param name="dbConnection">
      /// Database connection interface for making queries to a database
      /// </param>
      /// <param name="classQuestionID">
      /// ID of the class/question that is to be edited
      /// </param>
      /// <param name="questionTable">
      /// Question data
      /// </param>
      /// <param name="answerTable">
      /// Answer data
      /// </param>
      public AddEditQuestionForm(bool mode, DBConnection dbConnection, int classQuestionID, DataTable questionTable, DataTable answerTable)
      {
         InitializeComponent();

         this.mode = mode;
         this.dbConnection = dbConnection;
         
         this.questionTable = questionTable;
         this.answerTable = answerTable;

         answerID = 0;
         questionRowIndex = 0;
         questionNum = 0;

         if (mode == Defs.ADD_MODE)
         {
            this.newClassID = classQuestionID;
            buttonOk.Enabled = false;
         }
         else
         {
            this.questionID = classQuestionID;
            buttonOk.Enabled = true;
         }
      }

      /*
       * WINDOWS FORM EVENTS
       */

      private void AddEditQuestion_Load(object sender, EventArgs e)
      {
         questionRowIndex = HelperMethods.GetIndexOfTableID(questionTable, questionID);

         if (HelperMethods.CheckColumnsExists(questionTable, Defs.QUESTION_COLUMN_NAMES))
         {
            if (mode == Defs.EDIT_MODE)
            {
               QuestionType qType = HelperMethods.QuestionTypeStringToEnum(questionTable.Rows[questionRowIndex]["type"].ToString());
               questionNum = (int)questionTable.Rows[questionRowIndex]["number"];

               // multiple choice
               if (qType == QuestionType.MCQ)
               {
                  tabControl1.SelectTab("tabPageMCQ");
                  // TODO: remove tabpage from control
                  tabControl1.TabPages.Remove(tabControl1.TabPages["tabPageOPN"]);
                  tabControl1.TabPages.Remove(tabControl1.TabPages["tabPageTFQ"]);
                  LoadMCQQuestion();
               }
               // open
               else if (qType == QuestionType.OPN)
               {
                  tabControl1.SelectTab("tabPageOPN");
                  tabControl1.TabPages.Remove(tabControl1.TabPages["tabPageMCQ"]);
                  tabControl1.TabPages.Remove(tabControl1.TabPages["tabPageTFQ"]);
                  LoadOPNQuestion();
               }
               // true/false
               else if (qType == QuestionType.TFQ)
               {
                  tabControl1.SelectTab("tabPageTFQ");
                  tabControl1.TabPages.Remove(tabControl1.TabPages["tabPageMCQ"]);
                  tabControl1.TabPages.Remove(tabControl1.TabPages["tabPageOPN"]);
                  LoadTFQQuestion();
               }
            }
            else
            {
               relatedAnswers = new DataTable("RelatedAnswers");
               for (int i = 0; i < Defs.ANSWER_COLUMN_NAMES.Length; i++)
               {
                  relatedAnswers.Columns.Add(Defs.ANSWER_COLUMN_NAMES[i]);
                  relatedAnswers.Columns[Defs.ANSWER_COLUMN_NAMES[i]].ReadOnly = true;

                  if ((Defs.ANSWER_COLUMN_NAMES[i] == "id") ||
                      (Defs.ANSWER_COLUMN_NAMES[i] == "question"))
                  {
                     relatedAnswers.Columns[Defs.ANSWER_COLUMN_NAMES[i]].DataType = typeof(int);
                  }
                  else if (Defs.ANSWER_COLUMN_NAMES[i] == "iscorrect")
                  {
                     relatedAnswers.Columns[Defs.ANSWER_COLUMN_NAMES[i]].DataType = typeof(bool);
                  }
                  else
                  {
                     relatedAnswers.Columns[Defs.ANSWER_COLUMN_NAMES[i]].DataType = typeof(string);
                  }
               }

               dataGridViewAnswer.DataSource = relatedAnswers;
               dataGridViewAnswer.Columns["id"].Visible = false;
               dataGridViewAnswer.Columns["question"].Visible = false;
               dataGridViewAnswer.Columns["image"].Visible = false;
               dataGridViewAnswer.Columns["description"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
               dataGridViewAnswer.Columns["image"].AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
               dataGridViewAnswer.Sort(dataGridViewAnswer.Columns["id"], ListSortDirection.Ascending);

               // create edit data grid view button column
               DataGridViewButtonColumn buttonColumnEdit = new DataGridViewButtonColumn();
               buttonColumnEdit.HeaderText = "";
               buttonColumnEdit.Name = "edit";
               buttonColumnEdit.Text = "Edit";
               buttonColumnEdit.ToolTipText = "Edit the selected question";
               buttonColumnEdit.UseColumnTextForButtonValue = true;
               buttonColumnEdit.Width = 45;
               dataGridViewAnswer.Columns.Add(buttonColumnEdit);

               // create delete data grid view button column
               DataGridViewButtonColumn buttonColumnDelete = new DataGridViewButtonColumn();
               buttonColumnDelete.HeaderText = "";
               buttonColumnDelete.Name = "delete";
               buttonColumnDelete.Text = "Delete";
               buttonColumnDelete.ToolTipText = "Delete the selected answer";
               buttonColumnDelete.UseColumnTextForButtonValue = true;
               buttonColumnDelete.Width = 45;
               dataGridViewAnswer.Columns.Add(buttonColumnDelete);
            }
         }
      }

      /*
       * CONTROL EVENTS
       */

      private void buttonCancel_Click(object sender, EventArgs e)
      {
         this.Close();
      }

      private void buttonOk_Click(object sender, EventArgs e)
      {
         if (CheckCompleted())
         {
            string type = "OPN";
            string description = "";
            string answerDescription = "";
            string image = "NONE";

            // multiple choice
            if (tabControl1.SelectedIndex == 0)
            {
               type = "MCQ";
               description = textBoxQuestionMCQ.Text;
            }
            // open
            else if (tabControl1.SelectedIndex == 1)
            {
               type = "OPN";
               description = textBoxQuestionOPN.Text;
               answerDescription = textBoxAnswerOPN.Text;
            }
            // true/false
            else if (tabControl1.SelectedIndex == 2)
            {
               type = "TFQ";
               description = textBoxQuestionTFQ.Text;
               if (radioButtonTrue.Checked)
               {
                  answerDescription = Defs.TFQ_TRUE;
               }
               else
               {
                  answerDescription = Defs.TFQ_FALSE;
               }
            }

            if (mode == Defs.ADD_MODE)
            {
               // get all question data required for insert/updated
               string[] columnNames = new string[5] { 
                     "class", 
                     "number", 
                     "description", 
                     "type", 
                     "image" };
               object[] values = new object[5] { 
                     newClassID, 
                     questionNum, 
                     description, 
                     type, 
                     image };

               // insert the new question into the database
               int newQuestionID = dbConnection.InsertRecord("Question", columnNames, values);
               if (newQuestionID > 0)
               {
                  // insert into local storage
                  string[] newColumns = HelperMethods.CreateNewStringArray("id", columnNames);
                  object[] newValues = HelperMethods.CreateNewObjectArray(newQuestionID, values);
                  HelperMethods.InsertIntoTable(questionTable, newColumns, newValues);

                  columnNames = new string[4] { 
                           "question", 
                           "description", 
                           "iscorrect", 
                           "image" };

                  // if selected tab is open or true/false
                  if (tabControl1.SelectedIndex != 0)
                  {
                     values = new object[4] { 
                           newQuestionID, 
                           answerDescription, 
                           true, 
                           "NONE" };

                     int newAnswerID = dbConnection.InsertRecord("Answer", columnNames, values);
                     if (newAnswerID > 0)
                     {
                        newColumns = HelperMethods.CreateNewStringArray("id", columnNames);
                        newValues = HelperMethods.CreateNewObjectArray(newAnswerID, values);

                        if (tabControl1.SelectedIndex == 1)
                        {
                           if (textBoxAnswerOPN.Text != "")
                           {
                              HelperMethods.InsertIntoTable(answerTable, newColumns, newValues);
                           }
                           else
                           {
                              dbConnection.DeleteRecord("Answer", newAnswerID);
                              // do not need to delete from local storage since it doesn't exist
                           }
                        }
                        else if (tabControl1.SelectedIndex == 2)
                        {
                           HelperMethods.InsertIntoTable(answerTable, newColumns, newValues);
                        }
                     }
                  }
                  // if selected tab is multiple choice
                  else
                  {
                     for (int i = 0; i < relatedAnswers.Rows.Count; i++)
                     {
                        values = new object[4] {
                                 newQuestionID, 
                                 relatedAnswers.Rows[i]["description"],
                                 relatedAnswers.Rows[i]["iscorrect"],
                                 relatedAnswers.Rows[i]["image"] };

                        if ((int)relatedAnswers.Rows[i]["id"] == 0)
                        {
                           int newAnswerID = dbConnection.InsertRecord("Answer", columnNames, values);
                           if (newAnswerID > 0)
                           {
                              relatedAnswers.Columns["id"].ReadOnly = false;
                              relatedAnswers.Rows[i]["id"] = newAnswerID;
                              relatedAnswers.Columns["id"].ReadOnly = true;
                              newColumns = HelperMethods.CreateNewStringArray("id", columnNames);
                              newValues = HelperMethods.CreateNewObjectArray(newAnswerID, values);
                              HelperMethods.InsertIntoTable(answerTable, newColumns, newValues);
                           }
                        }
                     }
                  }

                  this.Close();
               }
            }
            else
            {
               if (questionID > 0)
               {
                  // get all question data required for insert/updated
                  int classID = (int)questionTable.Rows[questionRowIndex]["class"];
                  int questionNumber = (int)questionTable.Rows[questionRowIndex]["number"];
                  string[] columnNames = new string[5] { 
                     "class", 
                     "number", 
                     "description", 
                     "type", 
                     "image" };
                  object[] values = new object[5] { 
                     classID, 
                     questionNumber, 
                     description, 
                     type, 
                     image };

                  // update the database with the question
                  bool updated = dbConnection.UpdateRecord("Question", questionID, columnNames, values);
                  if (updated)
                  {
                     // update local question instructor data
                     HelperMethods.UpdateTable(questionTable, questionRowIndex, columnNames, values);

                     columnNames = new string[4] { 
                           "question", 
                           "description", 
                           "iscorrect", 
                           "image" };

                     // if selected tab is open or true/false
                     if (tabControl1.SelectedIndex != 0)
                     {
                        values = new object[4] { 
                           questionID, 
                           answerDescription, 
                           true, 
                           "NONE" };

                        updated = dbConnection.UpdateRecord("Answer", answerID, columnNames, values);
                        if (updated)
                        {
                           int answerRowIndex = HelperMethods.GetIndexOfTableID(answerTable, answerID);

                           if (tabControl1.SelectedIndex == 1)
                           {
                              if (textBoxAnswerOPN.Text != "")
                              {
                                 HelperMethods.UpdateTable(answerTable, answerRowIndex, columnNames, values);
                              }
                              else
                              {
                                 dbConnection.DeleteRecord("Answer", answerID);
                                 // do not need to delete from local storage since it doesn't exist
                              }
                           }
                           else if (tabControl1.SelectedIndex == 2)
                           {
                              HelperMethods.UpdateTable(answerTable, answerRowIndex, columnNames, values);
                           }
                        }
                        else
                        {
                           if (tabControl1.SelectedIndex == 1)
                           {
                              if (textBoxAnswerOPN.Text != "")
                              {
                                 int recordID = dbConnection.InsertRecord("Answer", columnNames, values);
                                 if (recordID > 0)
                                 {
                                    string[] newColumns = HelperMethods.CreateNewStringArray("id", columnNames);
                                    object[] newValues = HelperMethods.CreateNewObjectArray(recordID, values);
                                    HelperMethods.InsertIntoTable(answerTable, newColumns, newValues);
                                 }
                              }
                           }
                        }
                     }
                     // if selected tab is multiple choice
                     else
                     {
                        for (int i = 0; i < relatedAnswers.Rows.Count; i++)
                        {
                           values = new object[4] {
                                 relatedAnswers.Rows[i]["question"], 
                                 relatedAnswers.Rows[i]["description"],
                                 relatedAnswers.Rows[i]["iscorrect"],
                                 relatedAnswers.Rows[i]["image"] };

                           if ((int)relatedAnswers.Rows[i]["id"] > 0)
                           {
                              updated = dbConnection.UpdateRecord("Answer", (int)relatedAnswers.Rows[i]["id"], columnNames, values);
                              if (updated)
                              {
                                 int answerRowIndex = HelperMethods.GetIndexOfTableID(answerTable, (int)relatedAnswers.Rows[i]["id"]);
                                 HelperMethods.UpdateTable(answerTable, answerRowIndex, columnNames, values);
                              }
                           }
                           else if ((int)relatedAnswers.Rows[i]["id"] == 0)
                           {
                              int newAnswerID = dbConnection.InsertRecord("Answer", columnNames, values);
                              if (newAnswerID > 0)
                              {
                                 relatedAnswers.Columns["id"].ReadOnly = false;
                                 relatedAnswers.Rows[i]["id"] = newAnswerID;
                                 relatedAnswers.Columns["id"].ReadOnly = true;
                                 string[] newNames = HelperMethods.CreateNewStringArray("id", columnNames);
                                 object[] newValues = HelperMethods.CreateNewObjectArray(newAnswerID, values);
                                 HelperMethods.InsertIntoTable(answerTable, newNames, newValues);
                              }
                           }
                        }
                     }

                     this.Close();
                  }
               }
            }
         }
         else
         {
            string msg = "You have not fully comepleted the form for the select question type";
            MessageBox.Show(msg, "Incomplete form", MessageBoxButtons.OK, MessageBoxIcon.Hand);
         }
      }

      private void dataGridViewAnswer_CellClick(object sender, DataGridViewCellEventArgs e)
      {
         // Ignore clicks that are not on button cells. 
         if (e.RowIndex >= 0)
         {
            answerID = Int32.Parse(dataGridViewAnswer.Rows[e.RowIndex].Cells["id"].Value.ToString());

            // if the edit button was clicked
            if (e.ColumnIndex == dataGridViewAnswer.Columns["edit"].Index)
            {
               AddEditAnswerForm answerForm = new AddEditAnswerForm(Defs.EDIT_MODE, dbConnection,
                  questionID, answerID, relatedAnswers);
               answerForm.Text = "Editing answer";
               answerForm.ShowDialog();
            }
            // if the  delete button was clicked
            else if (e.ColumnIndex == dataGridViewAnswer.Columns["delete"].Index)
            {
               string confirmMsg = "Are you sure you want to delete the currently selected answer?";
               DialogResult confirmDelete = MessageBox.Show(confirmMsg, "Delete answer?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

               if (confirmDelete == DialogResult.Yes)
               {
                  int answerRowIndex = 0;
                  if (answerID == 0)
                  {
                     answerRowIndex = HelperMethods.GetIndexOfTableID(relatedAnswers, answerID);
                     relatedAnswers.Rows.RemoveAt(answerRowIndex);
                  }
                  else
                  {
                     answerRowIndex = HelperMethods.GetIndexOfTableID(answerTable, answerID);
                     bool deleted = dbConnection.DeleteRecord("Answer", answerID);
                     if (deleted)
                     {
                        answerTable.Rows.RemoveAt(answerRowIndex);
                        answerRowIndex = HelperMethods.GetIndexOfTableID(relatedAnswers, answerID);
                        relatedAnswers.Rows.RemoveAt(answerRowIndex);
                        //relatedAnswers = GetRelatedAnswers(answerTable, questionID);
                        dataGridViewAnswer.DataSource = relatedAnswers;
                        dataGridViewAnswer.Sort(dataGridViewAnswer.Columns["id"], ListSortDirection.Ascending);
                     }
                  }
               }
            }
         }
      }

      private void buttonAddAnswer_Click(object sender, EventArgs e)
      {
         AddEditAnswerForm newAnswer = new AddEditAnswerForm(Defs.ADD_MODE,
            dbConnection, 0, 0, relatedAnswers);
         newAnswer.Text = "Adding answer for question " + questionNum;
         newAnswer.ShowDialog();
      }

      private void textBoxQuestionMCQ_TextChanged(object sender, EventArgs e)
      {
         buttonOk.Enabled = true;
      }

      private void textBoxQuestionOPN_TextChanged(object sender, EventArgs e)
      {
         buttonOk.Enabled = true;
      }

      private void textBoxQuestionTFQ_TextChanged(object sender, EventArgs e)
      {
         buttonOk.Enabled = true;
      }

      /*
       * HELPER METHODS
       */

      private void LoadMCQQuestion()
      {
         if (HelperMethods.CheckColumnsExists(questionTable, Defs.QUESTION_COLUMN_NAMES))
         {
            dataGridViewAnswer.Columns.Clear();

            textBoxQuestionMCQ.Text = questionTable.Rows[questionRowIndex]["description"].ToString();

            relatedAnswers = GetRelatedAnswers(answerTable, questionID);
            dataGridViewAnswer.DataSource = relatedAnswers;
            dataGridViewAnswer.Columns["id"].Visible = false;
            dataGridViewAnswer.Columns["question"].Visible = false;
            dataGridViewAnswer.Columns["image"].Visible = false;
            dataGridViewAnswer.Columns["description"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            dataGridViewAnswer.Columns["iscorrect"].AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
            //dataGridViewAnswer.Columns["image"].AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
            dataGridViewAnswer.Sort(dataGridViewAnswer.Columns["id"], ListSortDirection.Ascending);

            // create edit data grid view button column
            DataGridViewButtonColumn buttonColumnEdit = new DataGridViewButtonColumn();
            buttonColumnEdit.HeaderText = "";
            buttonColumnEdit.Name = "edit";
            buttonColumnEdit.Text = "Edit";
            buttonColumnEdit.ToolTipText = "Edit the selected question";
            buttonColumnEdit.UseColumnTextForButtonValue = true;
            buttonColumnEdit.Width = 45;
            dataGridViewAnswer.Columns.Add(buttonColumnEdit);

            // create delete data grid view button column
            DataGridViewButtonColumn buttonColumnDelete = new DataGridViewButtonColumn();
            buttonColumnDelete.HeaderText = "";
            buttonColumnDelete.Name = "delete";
            buttonColumnDelete.Text = "Delete";
            buttonColumnDelete.ToolTipText = "Delete the selected answer";
            buttonColumnDelete.UseColumnTextForButtonValue = true;
            buttonColumnDelete.Width = 45;
            dataGridViewAnswer.Columns.Add(buttonColumnDelete);
         }
      }

      private void LoadOPNQuestion()
      {
         if (HelperMethods.CheckColumnsExists(questionTable, Defs.QUESTION_COLUMN_NAMES))
         {
            textBoxQuestionOPN.Text = questionTable.Rows[questionRowIndex]["description"].ToString();

            if (HelperMethods.CheckColumnsExists(answerTable, Defs.ANSWER_COLUMN_NAMES))
            {
               for (int i = 0; i < answerTable.Rows.Count; i++)
               {
                  if ((int)answerTable.Rows[i]["question"] == questionID)
                  {
                     answerID = (int)answerTable.Rows[i]["id"];
                     textBoxAnswerOPN.Text = answerTable.Rows[i]["description"].ToString();
                  }
               }
            }
         }
      }

      private void LoadTFQQuestion()
      {
         if (HelperMethods.CheckColumnsExists(questionTable, Defs.QUESTION_COLUMN_NAMES))
         {
            textBoxQuestionTFQ.Text = questionTable.Rows[questionRowIndex]["description"].ToString();

            if (HelperMethods.CheckColumnsExists(answerTable, Defs.ANSWER_COLUMN_NAMES))
            {
               for (int i = 0; i < answerTable.Rows.Count; i++)
               {
                  if ((int)answerTable.Rows[i]["question"] == questionID)
                  {
                     if ((bool)answerTable.Rows[i]["iscorrect"])
                     {
                        answerID = (int)answerTable.Rows[i]["id"];
                        string tfqAnswer = answerTable.Rows[i]["description"].ToString();

                        if (tfqAnswer.ToLower() == Defs.TFQ_TRUE)
                        {
                           radioButtonTrue.Checked = true;
                           return;
                        }
                        else
                        {
                           radioButtonFalse.Checked = true;
                           return;
                        }
                     }
                  }
               }
            }
         }
      }

      /// <summary>
      /// Given a table of answers, related questions are put into a new data table for display
      /// </summary>
      /// <param name="answers">
      /// Data table of answers
      /// </param>
      /// <param name="questionID">
      /// ID of the question which is used to retrieve related answers
      /// </param>
      /// <returns>
      /// Data table of related answers
      /// </returns>
      private DataTable GetRelatedAnswers(DataTable answers, int questionID)
      {
         DataTable newTable = new DataTable("RelatedAnswers");

         // add existing answer table column names to the new table
         for (int i = 0; i < answers.Columns.Count; i++)
         {
            string columnName = answers.Columns[i].ColumnName;
            DataColumn newColumn = new DataColumn(columnName, answers.Columns[i].DataType);
            newColumn.ReadOnly = true;
            newTable.Columns.Add(newColumn);
         }

         // copy rows from original table to the new table
         for (int i = 0; i < answers.Rows.Count; i++)
         {
            if (HelperMethods.CheckColumnsExists(answers, new string[1] {"question"}))
            {
               if ((int)answers.Rows[i]["question"] == questionID)
               {
                  object[] values = answers.Rows[i].ItemArray;
                  newTable.Rows.Add(values);
               }
            }
         }

         return newTable;
      }

      /// <summary>
      /// Checks if the controls in the forms have filled out correctly
      /// </summary>
      /// <returns>
      /// Whether or not the controls in the form are correctly filled out
      /// </returns>
      private bool CheckCompleted()
      {
         // multiple choice
         if (tabControl1.SelectedIndex == 0)
         {
            if ((textBoxQuestionMCQ.Text != "") &&
                (dataGridViewAnswer.Rows.Count > 0))
            {
               return true;
            }
            else
            {
               return false;
            }
         }
         // open
         else if (tabControl1.SelectedIndex == 1)
         {
            if (textBoxQuestionOPN.Text != "")
            {
               return true;
            }
            else
            {
               return false;
            }
         }
         // true/false
         else if (tabControl1.SelectedIndex == 2)
         {
            if (textBoxQuestionTFQ.Text != "")
            {
               return true;
            }
            else
            {
               return false;
            }
         }
         else
         {
            return false;
         }
      }

      /*
       * PROPERTIES
       */

      /// <summary>
      /// Property used for adding a question number to the question.
      /// Used when creating a new question
      /// </summary>
      public int NewNumber
      {
         set
         {
            questionNum = value;
         }
      }
   }
}
